package com.yonyou.crm.bpub.approval.service;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import yonyou.bpm.rest.exception.RestException;
import yonyou.bpm.rest.request.RestVariable;
import yonyou.bpm.rest.response.CommentResponse;
import yonyou.bpm.rest.response.ParticipantResponse;
import yonyou.bpm.rest.response.historic.HistoricProcessInstanceResponse;
import yonyou.bpm.rest.response.historic.HistoricTaskInstanceResponse;
import yonyou.bpm.rest.response.identity.TenantResponse;
import yonyou.bpm.rest.response.identity.UserResponse;
import yonyou.bpm.rest.response.repository.ProcessDefinitionResponse;
import yonyou.bpm.rest.response.runtime.task.RejectInfoItemResponse;
import yonyou.bpm.rest.response.runtime.task.TaskResponse;

import com.yonyou.crm.bpub.approval.entity.ActionEnum;
import com.yonyou.crm.bpub.approval.entity.ActionVO;
import com.yonyou.crm.bpub.approval.entity.ApprovalStatusEnum;
import com.yonyou.crm.bpub.approval.entity.AssigneeVO;
import com.yonyou.crm.bpub.approval.entity.BpubTenantDO;
import com.yonyou.crm.bpub.approval.entity.DjInfoVO;
import com.yonyou.crm.bpub.approval.entity.DjTypeEnum;
import com.yonyou.crm.bpub.approval.entity.HistoryVO;
import com.yonyou.crm.bpub.approval.entity.ProcessInstanceDO;
import com.yonyou.crm.bpub.approval.entity.ProcessInstanceVO;
import com.yonyou.crm.bpub.approval.entity.ProcessModelDO;
import com.yonyou.crm.bpub.approval.entity.ProcessModelVO;
import com.yonyou.crm.bpub.approval.entity.SuperVO;
import com.yonyou.crm.bpub.approval.entity.TaskVO;
import com.yonyou.crm.bpub.approval.util.ProcessObjectInfoFactory;
import com.yonyou.crm.bpub.approval.util.ProcessObtainUtil;
import com.yonyou.crm.bpub.detail.service.DetailsBizServiceImpl;
import com.yonyou.crm.bpub.itf.IProcessService;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.exception.CrmMessageException;
import com.yonyou.crm.common.login.context.LoginContextConstant;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.crm.common.rest.constant.CrmCodeConstant;
import com.yonyou.crm.csns.im.param.IMType;
import com.yonyou.crm.csns.im.param.ImParam;
import com.yonyou.crm.csns.im.service.ImBizServiceImpl;
import com.yonyou.crm.sys.org.service.SysOrgBizServiceImpl;
import com.yonyou.crm.sys.role.entity.RoleVO;
import com.yonyou.crm.sys.role.service.RoleBizServiceImpl;
import com.yonyou.crm.sys.tenant.entity.SysTenantVO;
import com.yonyou.crm.sys.tenant.service.SysTenantBizServiceImpl;
import com.yonyou.crm.sys.user.entity.UserVO;
import com.yonyou.crm.sys.user.service.UserBizServiceImpl;
import com.yonyou.iuap.context.InvocationInfoProxy;

@Service("ProcessBizServiceImpl")
public class ProcessBizServiceImpl  {
	private Logger log = LoggerFactory.getLogger(getClass());
	@Autowired
	BpubTenantBizServiceImpl bpubTenantService;
	
	@Autowired
	ApprovalUserBizServiceImpl approvalUserService;
	
	@Autowired
	ProcessModelBizServiceImpl modelService;
	
	@Autowired
	ProcessInstanceBizServiceImpl instanceService;
	
	@Autowired
	SysTenantBizServiceImpl tenantService;
	
	@Autowired
	SysOrgBizServiceImpl sysOrgService;
	
	@Autowired
	UserBizServiceImpl userService;
	
	@Autowired
	RoleBizServiceImpl roleService;
	
	@Autowired
	YsService ysService;
	
	@Autowired
	JsonResultService jsonResultService;
	
	@Autowired
	DetailsBizServiceImpl detailService;
	
	@Autowired
	private ApplicationContext applicationContext;
	
	@Autowired
	private ImBizServiceImpl imBizService;
    
    private String domain = "http://123.103.9.190:81/ubpm-web-approve/";
    
    /*
     * 将iso日期格式转化为date
     */
//    private Date isoDate2Date(String isoDate) throws ParseException {
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
//		Date date = sdf.parse(isoDate);
//		return date;
//    }
	
	/*
	 * 计算时间间隔，返回格式为：小于一天的显示时分，如5小时25分；大于1天的显示天时，如3天5小时
	 */
	private String getDurationTime(Date date1, Date date2) {
		long time1 = date1.getTime(); 
		long time2 = date2.getTime();
		
		long durationMill = Math.abs(time2 - time1);
		
		long dayMill = 1000 * 60 * 60 *24;
		long yu = durationMill;
		long days = 0;
		if (durationMill > dayMill) {
			yu = durationMill%dayMill;
			days = (durationMill - yu) /dayMill;
		}
		
		long hourMill = 1000 * 60 * 60;
		long seconds = yu%hourMill;
		long hours = (yu-seconds)/hourMill;
		
		String durationStr = "";
		if (days > 0) {
			durationStr = days + "天" + hours + "小时";
		} else {
			long minutes = seconds/(1000 * 60);
			durationStr = hours + "小时" + minutes + "分";
		}
//		durationStr = "已停留 " + durationStr;
		return durationStr;
	}
    
    /*
     * 获取租户在云审的id
     */
    public String getYsTenantId(Long tenantId){
    	if (tenantId == null) {
    		tenantId = Long.parseLong(InvocationInfoProxy.getTenantid());
    	}
    	String ysTenantId = bpubTenantService.getYsTenantId(tenantId);
    	if (ysTenantId == null || ysTenantId.equals("")) {
    		throw new CrmBusinessException(CrmCodeConstant.ServerError, "租户没有审批模块权限");
    	}
    	return ysTenantId;
    }
    
    /*
     * 获取用户在云审的id(如果未同步人员，直接报错)
     */
    private String getYsUserId(Long userId){
    	if (userId == null) {
    		userId = Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId));
    	}
    	String ysUserId = approvalUserService.getYsUserId(userId);
    	if (ysUserId == null || ysUserId.equals("")) {
    		throw new CrmBusinessException(CrmCodeConstant.ServerError, "用户没有审批模块权限");
    	}
    	return ysUserId;
    }
    
    private String getYsInstanceId(Long businessId, int djType){
    	ProcessInstanceVO instanceVO = instanceService.selectByPk(businessId, djType);
    	if (instanceVO == null) {
    		throw new CrmBusinessException(CrmCodeConstant.ServerError, "单据不存在");
    	}
    	return instanceVO.getYsInstanceId();
    }
	
	/*
	 * 获取单点登录云审批设计器的url(含domain,即绝对路径)
	 */
	private String getAbsoluteUrlForLoginYs(String modelId) {
		String url = getUrlForLoginYs(modelId);
		if (url.startsWith("http")) {
			return url;
		}
		url = domain + url;
		return url;
	}
	
	/*
	 * 获取单点登录云审批设计器的url(不含domain，即相对路径)
	 */
	public String getUrlForLoginYs(String modelId) {
//		String userId = "6e67e1ac-d0e1-11e7-b424-0242ac1e1584";
		
		Long userId = Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId));
		String ysUserId = getYsUserId(userId);
		Long tenantId = Long.parseLong(InvocationInfoProxy.getTenantid());
		String ysTenantId = getYsTenantId(tenantId);
		
		return ysService.getUrlForLoginYs(ysUserId, ysTenantId, userId.toString(), modelId);
	}
	
	/*
	 * 获取审批流列表
	 */
	public List<ProcessModelVO> getProcessModelList(Map<String, Object> paraMap) {
//		String ysUserId = getYsUserId(null);
//		String ysTenantId = getYsTenantId(null);
//		try {
//			ysService.getProcessDefinitionModels(ysUserId, ysTenantId, 1, 10);
//		} catch (RestException e) {
//			// TODO 自动生成的 catch 块
//			e.printStackTrace();
//		}
		List<ProcessModelVO> list = modelService.getProcessModelList(paraMap);
		return list;
	}
	
	/*
	 * 获取流水号
	 */
//	private String getSerialNumber(Date date) {
//		Calendar calendar = Calendar.getInstance();
//		if (date == null) {
//			date = calendar.getTime();
//		}
//		
//		int year = calendar.get(Calendar.YEAR);    //获取年
//		int month = calendar.get(Calendar.MONTH) + 1;   //获取月份，0表示1月份
//		String monthStr = month < 10 ? "0" + month : String.valueOf(month);
//		int day = calendar.get(Calendar.DAY_OF_MONTH); // 获取天
//		String dayStr = day < 10 ? "0" + day : String.valueOf(day);
//		long millis = calendar.getTimeInMillis(); // 毫秒数
//		
//		String serialNum = year + monthStr + dayStr + millis;
//		return serialNum;
//	}
	
	/*
	 * 设计流程模型,返回流程模型设计器url
	 */
	public String createProcess(Map<String, Object> paraMap) {
		int djType = (int)paraMap.get("djType");
		Long bizTypeId = (Long)paraMap.get("bizTypeId");
		
		// 流程模型已存在，则直接返回url
		ProcessModelVO modelVO = modelService.selectByType(bizTypeId, djType);
		if (modelVO != null && modelVO.getId() != null) {
			return getAbsoluteUrlForLoginYs(modelVO.getYsModelId());
		}
		
		String key = "";
		String djTypeName = "";
		
		for (DjTypeEnum djTypeEnum: DjTypeEnum.values()) {
			if (djTypeEnum.getValue() == djType) {
				key = djTypeEnum.toString();
				djTypeName = djTypeEnum.getName();
				break;
			}
		}
		
		if (key.isEmpty()) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "请选择正确的单据类型");
		}
		
		key += "_" + djType + "_" + bizTypeId;
		String name = djTypeName;
//		String serialNum = getSerialNumber(null);
//		String name = djTypeName + serialNum;
		
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		String modelId = "";
		try {
			ProcessDefinitionResponse responseMap = ysService.createProcessDefinitionModel(ysUserId, ysTenantId, key, name);
			modelId = responseMap.getId();
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "创建流程模型失败");
		}
		
		if (modelId.isEmpty()) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "创建流程模型失败");
		}
		
		// 将流程定义模型的id，key等与单据类型业务类型的映射保存到本地库
		String url = getUrlForLoginYs(modelId);
	    ProcessModelDO processModelDO = new ProcessModelDO();
	    processModelDO.setTenantId(Long.parseLong(InvocationInfoProxy.getTenantid()));
	    processModelDO.setBizTypeId(bizTypeId);
	    processModelDO.setDjType(djType);
	    processModelDO.setYsModelName(name);
	    processModelDO.setYsModelId(modelId);
	    processModelDO.setYsModelKey(key);
	    processModelDO.setYsUrl(url);
	    modelService.saveVO(processModelDO);

		return domain + url;
	}
	
	/*
	 * 删除流程定义模型
	 */
	public boolean deleteProcessModel(String modelId){
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		try {
			ysService.deleteProcessModel(ysUserId, ysTenantId, modelId);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "删除流程失败");
		}
		
		modelService.deleteByModelId(modelId);
		// TODO 是否需要删除相关的实例(需要确认需求)
		return true;
	}
	
	/*
	 * 启动流程,实际业务中，启动流程后，要给具体业务数据回写部分审批流状态数据
	 * @paraMap 
	 * djType:单据类型key
	 * bizTypeId:业务类型id
	 * businessId:业务数据id
	 */
	public void startProcess(Map<String, Object> paraMap) {

		int djType = (int)paraMap.get("djType");
		Long bizTypeId = (Long)paraMap.get("bizTypeId");
		Long businessId = (Long)paraMap.get("businessId");
		String businessIdStr = businessId.toString();
		String instanceName = (String)paraMap.get("instanceName");
		
		ProcessModelVO modelVO = modelService.selectByType(bizTypeId, djType);
		if (modelVO == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "找不到审批流");
		}
		
		// 判断单据是否已提交
		ProcessInstanceVO instanceVO = instanceService.selectByPk(businessId, djType);
		if (instanceVO != null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "单据已提交");
		}

		
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		
		List<RestVariable> variables = new ArrayList<RestVariable>();
		RestVariable variable = new RestVariable();
		variable.setName("formurl");
		variable.setType("string");
		String formurl = "";
		variable.setValue(formurl);
		variables.add(variable);
		 
		variable = new RestVariable();
		variable.setName("formid");
		variable.setType("string");
		variable.setValue(businessIdStr);
		variables.add(variable);
		 
		variable = new RestVariable();
		variable.setName("formname");
		variable.setType("string");
		variable.setValue(instanceName);
		variables.add(variable);
		
		String processKey = modelVO.getYsModelKey();
		String instanceId = "";
		try {
			HistoricProcessInstanceResponse resp = ysService.startProcess(ysUserId, ysTenantId, processKey, businessIdStr, instanceName, variables);
			instanceId = resp.getId();
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "启动流程失败");
		}
		
		if (instanceId.isEmpty()) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "启动流程失败");
		}
		
		// 保存数据到instance表
		ProcessInstanceDO instanceDO = new ProcessInstanceDO();
		instanceDO.setBusinessId(businessId);
		instanceDO.setDjType(djType);
		instanceDO.setTenantId(Long.parseLong(InvocationInfoProxy.getTenantid()));
		instanceDO.setYsInstanceId(instanceId);
		instanceDO.setYsModelKey(processKey);
		instanceDO.setUserId(Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId)));
		
		instanceService.saveVO(instanceDO);
	}
	
	/*
	 * 删除流程实例(撤回申请)
	 */
	private boolean deleteProcessInstance(Long businessId, int djType) {

		String instanceId = getYsInstanceId(businessId, djType);
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		
		boolean rs = false;
		try {
			rs = ysService.deleteProcessInstance(ysUserId, ysTenantId, instanceId);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "撤回申请失败");
		}
		instanceService.deleteByPk(businessId, djType);
		return rs;
	}
	
	public boolean deleteProcessInstance(String instanceId) {
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		
		boolean rs = false;
		try {
			rs = ysService.deleteProcessInstance(ysUserId, ysTenantId, instanceId);
			return rs;
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "撤回申请失败");
		}
	}
	
	/*
	 * 判断流程实例是否可以撤回
	 */
	public boolean canCancelInstance(Long businessId, int djType) {
		String instanceId = getYsInstanceId(businessId, djType);
		String ysUserId = getYsUserId(null);
		String ysTenantId = getYsTenantId(null);
		
		try {
			HistoricProcessInstanceResponse info = ysService.getProcessInstanceAllInfo(ysUserId, ysTenantId, instanceId);
			if (info == null) {
				return false;
			}
			if (!(info.getStartUserId().equals(ysUserId))) return false; 
			return canCancelInstance(info);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取审批动作失败");
		}
	}
	
	private boolean canCancelInstance(HistoricProcessInstanceResponse info) {
		
/*		// 判断表单撤回设置条件，withdrawAll 为true，表示只要流程实例未完成，就可撤回
		if (info.isWithdrawAll()) {
			// 流程实例未完成
			if (info.getEndTime() == null) return true;
			// 流程实例完成
			return false;
		}
		// withdrawAll为false， 表示表单撤回设置条件为仅在第一个审批环节未完成时可撤回
		// 有任务已完成，不可撤回
		if (info.getHasTaskFinished()) return false;
		// 没有任务完成，可撤回
*/		return true;
	}
	
	/*
	 * 撤回(撤回后，修改单据审批状态字段值为0，表示撤回或者被驳回制单人)
	 */
	public boolean cancelApproval(Long businessId, int djType) {
		boolean cancancel = canCancelInstance(businessId, djType);
		if (!cancancel) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "单据不可撤回");
		}
		boolean isSuccess = deleteProcessInstance(businessId, djType);
		updateApprovalState(businessId, djType, 0, null);
		return isSuccess;
	}
	/**
	 * 更新流程的状态。根据djType来确定使用那个实现类
	 * @param businessId
	 * @param djType
	 * @param approvalState
	 * @param paraMap
	 */
	private void updateApprovalState(Long businessId, int djType, int approvalState, Map<String, Object> paraMap) {
		IProcessService service = new ProcessObtainUtil().getProcessService(djType, applicationContext);
		service.updateApprovalState(businessId, approvalState, paraMap);
	}
	
	/*
	 * 获取待审人
	 */
	public List<AssigneeVO> getNextTaskAssignees(Long businessId, int djType) {
		String instanceId = getYsInstanceId(businessId, djType);
		return getNextTaskAssignees(instanceId);
	}
	
	private List<AssigneeVO> getNextTaskAssignees(String instanceId) {
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		return queryNextTaskAssignees(ysUserId, ysTenantId, instanceId);
	}
	
	private List<AssigneeVO> queryNextTaskAssignees(String ysUserId, String ysTenantId, String instanceId) {
		List<HistoricTaskInstanceResponse> list = null;
		try {
			list = ysService.queryInstanceNotFinishTaskAssigneeList(ysUserId, ysTenantId, instanceId, null);
			
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取待审人失败");
		}
		if (list == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取待审人失败");
		}
		
		List<AssigneeVO> assigneeVOs = new ArrayList<AssigneeVO>();

		for (HistoricTaskInstanceResponse map : list) {
			AssigneeVO assigneeVO = new AssigneeVO();
			ParticipantResponse assigneeParticipant = map.getAssigneeParticipant();
			String assigneeCode = assigneeParticipant.getCode();
			Long assigneeId = Long.parseLong(assigneeCode.split("_")[1]);
			assigneeVO.setId(assigneeId);
			assigneeVO.setName(assigneeParticipant.getName());
			assigneeVOs.add(assigneeVO);
		}
		
		return assigneeVOs;
	}
	
	/*
	 * 获取单据审批历史
	 */
	public List<HistoryVO> getHistoryTasks(Long businessId, int djType, String order) {
		List<HistoryVO> historyVOs = new ArrayList<HistoryVO>();
		String instanceId = "";
		try {
			instanceId = getYsInstanceId(businessId, djType);
		} catch (CrmBusinessException e) {
			return historyVOs;
		}
		
		if (instanceId.isEmpty()) {
			return historyVOs;
		}
		
		String ysTenantId = getYsTenantId(null);
		String ysUserId = getYsUserId(null);
		
		// 排序
		if (order == null || !(order.equals("desc") || order.equals("asc")) ) {
			order = "desc";
		}
		
		List<HistoricTaskInstanceResponse> list = null;
		try {
			// 获取所有任务
			list = ysService.queryInstanceAllHistoryTaskList(ysUserId, ysTenantId, instanceId, order, null);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取审批历史失败");
		}
		if (list == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取审批历史失败");
		}
		
		HistoricProcessInstanceResponse instanceInfo = list.get(0).getHistoricProcessInstance();
		ParticipantResponse startInfo = instanceInfo.getStartParticipant();
		Date startTime = instanceInfo.getStartTime();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		String time = "";
		List<HistoricTaskInstanceResponse> todoTasks = new ArrayList<HistoricTaskInstanceResponse>();
		HistoryVO historyVO;
		
		for (HistoricTaskInstanceResponse resp : list) {
			String state = resp.getState();
			if (state.contains("delete")) continue;

			String deleteReason = resp.getDeleteReason();
			if (deleteReason != null && deleteReason.equals("deleted")) continue;
			
			Boolean finished = resp.isFinished();
			if (!finished) {
				todoTasks.add(resp);
				continue;
			}

			historyVO = new HistoryVO();
			ParticipantResponse assigneeParticipant =resp.getAssigneeParticipant();
			List<AssigneeVO> personlist = new ArrayList<AssigneeVO>();
			AssigneeVO person = new AssigneeVO();
			String assigneeCode = assigneeParticipant.getCode();
			Long assigneeId = Long.parseLong(assigneeCode.split("_")[1]);
			person.setId(assigneeId);
			person.setName(assigneeParticipant.getName());
			personlist.add(person);
			historyVO.setPersonlist(personlist);
			
			List<CommentResponse> taskComments = resp.getTaskComments();
			if (taskComments == null || taskComments.size() == 0) {
				historyVO.setComment("");
			} else {
				historyVO.setComment(taskComments.get(0).getMessage());
			}
			
			// 已审
			historyVO.setIsremind("N");
			String status = "";
			
			switch (deleteReason) {
				case "completed":
					status = "同意";
					break;
				case "reject":
				case "rejectall":
				case "delete":
					status = "驳回";
					break;
				default:
//					status = "待审";
					break;
			}
			historyVO.setStatus(status);
			Date endTime = resp.getEndTime();
			if (endTime == null) {
				historyVO.setTime("");
			} else {
				time = sdf.format(endTime);
				historyVO.setTime(time);
			}
			historyVOs.add(historyVO);
		}
		
		historyVO = new HistoryVO();
		List<AssigneeVO> assigneeVOs = new ArrayList<AssigneeVO>();
		AssigneeVO assigneeVO = new AssigneeVO();
		String startUserCode = startInfo.getCode();
		Long startUserId = Long.parseLong(startUserCode.split("_")[1]);
		assigneeVO.setId(startUserId);
		assigneeVO.setName(startInfo.getName());
		assigneeVOs.add(assigneeVO);
		historyVO.setPersonlist(assigneeVOs);
		historyVO.setIsremind("N");
		historyVO.setStatus("提交");
		historyVO.setComment("");
		time = sdf.format(startTime);
		historyVO.setTime(time);
		if (order.equals("desc")) {
			historyVOs.add(historyVO);
		} else {
			historyVOs.add(0, historyVO);
		}
		
		// 待审
		int todoSize = todoTasks.size();
		if (todoSize == 0) {
			return historyVOs;
		}
		historyVO = new HistoryVO();
		historyVO.setIsremind("Y");
		historyVO.setStatus("待审");
		startTime = todoTasks.get(todoSize - 1).getStartTime();
		if (startTime == null) {
			historyVO.setTime("");
		} else {
			historyVO.setTime(getDurationTime(startTime, new Date()));
		}
		List<AssigneeVO> todoUsers = new ArrayList<AssigneeVO>();
		for (HistoricTaskInstanceResponse resp : todoTasks) {
			ParticipantResponse assigneeParticipant =resp.getAssigneeParticipant();
			
			AssigneeVO person = new AssigneeVO();
			String assigneeCode = assigneeParticipant.getCode();
			Long assigneeId = Long.parseLong(assigneeCode.split("_")[1]);
			person.setId(assigneeId);
			person.setName(assigneeParticipant.getName());
			todoUsers.add(person);
		}
		historyVO.setPersonlist(todoUsers);
		if (order.equals("desc")) {
			historyVOs.add(0, historyVO);
		} else {
			historyVOs.add(historyVO);
		}
		
		return historyVOs;
	}
	
	/*
	 * 获取发起人发起的流程实例数量
	 */
	public int getProcessInstancesCount(Boolean isFinished) {
		String ysUserId = getYsUserId(null);
		String ysTenantId = getYsTenantId(null);
		
		try {
			return ysService.getHistoricProcessInstancesCount(ysUserId, ysTenantId, null, isFinished);
		} catch (RestException e) {
			e.printStackTrace();
//			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取提交单据数量失败");
			return 0;
		}
	}
	
	/*
	 * 获取任务数量
	 */
	public int getTasksCount(Boolean isFinished) {
		String ysUserId = getYsUserId(null);
		String ysTenantId = getYsTenantId(null);
		
		try {
			return ysService.getHistoricTasksCount(ysUserId, ysTenantId, null, isFinished);
		} catch (RestException e) {
			e.printStackTrace();
//			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取任务数量失败");
			return 0;
		}
	}
	
	/*
	 * 获取某人发起的流程实例列表(已完成，未完成)
	 */
	public Page<DjInfoVO> getProcessInstanceList(Boolean isFinished, Map<String, Object> paraMap) {
		Page<HistoricProcessInstanceResponse> startList = queryStartList(isFinished, paraMap);
		List<HistoricProcessInstanceResponse> dataList = startList.getData();
		if (dataList == null) {
			dataList = new ArrayList<HistoricProcessInstanceResponse>();
		}
		
		Page<DjInfoVO> rsPage = new Page<DjInfoVO>();
		int page = startList.getPage();
		int pageSize = startList.getPageSize();
		rsPage.setPage(startList.getPage());
		rsPage.setPageSize(startList.getPageSize());
		
		List<DjInfoVO> instanceVOs = new ArrayList<DjInfoVO>();
		int i = ((page - 1) * pageSize) + 1;
		long total = startList.getTotal();
		
		for (HistoricProcessInstanceResponse resp : dataList) {
			// 查询实例是否存在
			String instanceId = resp.getId();
			ProcessInstanceVO pInstanceVO = instanceService.selectByInstanceId(instanceId);
			if (pInstanceVO == null) {
				total--;
				continue;
			}
			
			String ysModelId = resp.getProcessDefinitionId();
			String ysModelKey = ysModelId.split(":")[0];
			ProcessModelVO modelVO = modelService.selectByYsModelKey(ysModelKey);
			if (modelVO == null) continue;
			
			DjInfoVO instanceVO = new DjInfoVO();
			instanceVO.setId(i);
			instanceVO.setDjType(modelVO.getDjType()); 
			
			instanceVO.setInstanceId(instanceId);
			instanceVO.setName(resp.getName());
			
			// 未完成单据，查询待审人列表
			if (isFinished) {
				if(modelVO.getDjType() == DjTypeEnum.CUM_PRMT.getValue()){//客户升级申请单
					IProcessService service = new ProcessObtainUtil().getProcessService(modelVO.getDjType(),applicationContext);
					SuperVO vo = (SuperVO)service.selectById(pInstanceVO.getBusinessId());
					Long approvalUserId = vo.getApprovalUserId();
					List<AssigneeVO> approvalUserList = new ArrayList<AssigneeVO>();
//					Long approvalUserId = prmtVO.getApprovalUserId();
					if (approvalUserId == null || approvalUserId.equals(0L)) {
						AssigneeVO assigneeVO = new AssigneeVO();
						assigneeVO.setId(approvalUserId);
						assigneeVO.setName(vo.getApprovalUserName());
						approvalUserList.add(assigneeVO);
					}
					instanceVO.setApprovalUserList(approvalUserList);
				}
			} else {
				List<AssigneeVO> approvalUserList = getNextTaskAssignees(instanceId);
				instanceVO.setApprovalUserList(approvalUserList);
			}
			try {
				Date startTimeD = resp.getStartTime();
				instanceVO.setCreateTime(startTimeD);
				
				if (isFinished) {
					// 已完成单据返回完成时间
					instanceVO.setCompleteTime(resp.getEndTime());
					//TODO返回最后审批人
					if(modelVO.getDjType() == DjTypeEnum.CUM_PRMT.getValue()){//客户升级申请单
						IProcessService service = new ProcessObtainUtil().getProcessService(modelVO.getDjType(),applicationContext);
						SuperVO vo = (SuperVO)service.selectById(pInstanceVO.getBusinessId());
						List<AssigneeVO> approvalUserList = new ArrayList<AssigneeVO>();
						AssigneeVO assigneeVO = new AssigneeVO();
						assigneeVO.setId(vo.getApprovalUserId());
						assigneeVO.setName(vo.getApprovalUserName());
						approvalUserList.add(assigneeVO);
						instanceVO.setApprovalUserList(approvalUserList);
					}
				} else {
					// 未完成单据返回当前阶段停留时长
					String stayTimeLength = getDurationTime(startTimeD, new Date());
					instanceVO.setStayTimeLength(stayTimeLength);
					instanceVO.setOperate("提醒");
				}
			} catch (Exception e) {
				throw new CrmBusinessException(CrmCodeConstant.ServerError, "时间格式转化失败");
			}

			instanceVO.setDjId(Long.parseLong(resp.getBusinessKey()));
			
			String statusName = "";
			int status = 0;
			if (isFinished) {
				statusName = "审批历史";
				status = 1;
			} else {
				statusName = "审批进行中";
			}
			instanceVO.setStatus(status);
			instanceVO.setStatusName(statusName);
			
			instanceVOs.add(instanceVO);
			i++;
		}
		rsPage.setTotal(total);
		rsPage.setData(instanceVOs); 
		return rsPage;
	}
	
	/*
	 * 查询流程实例列表(即提交的申请列表,条件含已完成，未完成等)
	 */
	private Page<HistoricProcessInstanceResponse> queryStartList(Boolean isFinished, Map<String, Object> paraMap) {
		Page<HistoricProcessInstanceResponse> rsPage = new Page<HistoricProcessInstanceResponse>();
		String ysUserId = "";
		String ysTenantId = "";
		try {
			ysUserId = getYsUserId(null);
			ysTenantId = getYsTenantId(null);
		}  catch (CrmBusinessException e) {
			e.printStackTrace();
			return rsPage;
		}
		
		try {
			return ysService.queryStartList(ysUserId, ysTenantId,paraMap, isFinished);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取列表失败");
		}
	}
	
	/*
	 * 查询待办任务
	 */
	public Page<TaskVO> getTasksTodo(Map<String, Object> paraMap) {
		Page<TaskVO> rsPage = new Page<TaskVO>();
		String ysUserId = "";
		String ysTenantId = "";
		try {
			ysUserId = getYsUserId(null);
			ysTenantId = getYsTenantId(null);
		}  catch (CrmBusinessException e) {
			e.printStackTrace();
			return rsPage;
		}
		
		Integer page = (Integer)paraMap.get("page");
		Integer pageSize = (Integer)paraMap.get("pageSize");
		
		Page<TaskResponse> pageList = null;
		try {
			pageList = ysService.queryTasksTodo(ysUserId, ysTenantId, paraMap);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取待办列表失败");
		}

		List<TaskVO> taskVOs = new ArrayList<TaskVO>();
		int i = ((page - 1) * pageSize) + 1;
		long total = pageList.getTotal();

		List<TaskResponse> dataList = pageList.getData();
		if (dataList == null) {
			dataList = new ArrayList<TaskResponse>();
		}
		for (TaskResponse resp : dataList) {
			String processInstanceId = resp.getProcessInstanceId();
			ProcessInstanceVO instanceVO = instanceService.selectByInstanceId(processInstanceId);
			if (instanceVO == null) {
				total--;
				continue;
			}
			
			HistoricProcessInstanceResponse instanceMap = null;
			try {
				instanceMap = ysService.getProcessInstanceAllInfo(ysUserId, ysTenantId, processInstanceId);
			} catch (RestException e1) {
				e1.printStackTrace();
			}
			if (instanceMap == null) continue;

			TaskVO taskVO = new TaskVO();
			taskVO.setId(i);
			taskVO.setTaskId(resp.getId());
			taskVO.setDjId(instanceVO.getBusinessId());
			taskVO.setDjType(instanceVO.getDjType());
			
			taskVO.setInstanceId(processInstanceId);
			
			String name = resp.getProcessInstance().getName();
			taskVO.setName(name);
//			UserVO startUserVO = userService.getDetail(instanceVO.getUserId());
//			taskVO.setName(startUserVO.getName() + "提交的" + name);
			
			try {
				Date createTimeD = resp.getCreateTime();
				taskVO.setCreateTime(createTimeD);
				
				String stayTimeLength = getDurationTime(createTimeD, new Date());
				taskVO.setStayTimeLength(stayTimeLength);
			} catch (Exception e) {
				throw new CrmBusinessException(CrmCodeConstant.ServerError, "时间格式转化失败");
			}
			
			taskVOs.add(taskVO);
			i++;
		}
		
		rsPage.setTotal(total);
		rsPage.setPage(page);
		rsPage.setPageSize(pageSize);
		rsPage.setData(taskVOs);
		return rsPage;
	}
	
	/*
	 * 查询已办任务
	 */
	public Page<TaskVO> getTasksDone(Map<String, Object> paraMap) {
		Page<TaskVO> rsPage = new Page<TaskVO>();
		String ysUserId = "";
		String ysTenantId = "";
		try {
			ysUserId = getYsUserId(null);
			ysTenantId = getYsTenantId(null);
		}  catch (CrmBusinessException e) {
			e.printStackTrace();
			return rsPage;
		}
		
		String taskDue = null;
		String taskToday = null;
		Integer priority = null;
		
		Page<HistoricTaskInstanceResponse> taskList = null;
		try {
			taskList = ysService.queryTasksDone(ysUserId, ysTenantId, taskDue, taskToday, priority,paraMap);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取已办列表失败");
		}
		
		if (taskList == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "获取已办列表失败");
		}
		
		List<HistoricTaskInstanceResponse> dataList = taskList.getData();
		if (dataList == null) {
			dataList = new ArrayList<HistoricTaskInstanceResponse>();
		}
		int page = taskList.getPage();
		int pageSize = taskList.getPageSize();
		rsPage.setPage(page);
		rsPage.setPageSize(pageSize);
		
		List<TaskVO> taskVOs = new ArrayList<TaskVO>();
		int i = ((page - 1) * pageSize) + 1;
		long total = taskList.getTotal();
		
		for (HistoricTaskInstanceResponse resp:dataList) {
			TaskVO taskVO = new TaskVO();
			taskVO.setId(i);
			taskVO.setTaskId(resp.getId());
			
			String instanceId = resp.getProcessInstanceId();
			taskVO.setInstanceId(instanceId);
			
			ProcessInstanceVO instanceVO = instanceService.selectByInstanceId(instanceId);
			if (instanceVO == null) {
				total--;
				continue;
			}
			
			taskVO.setDjId(instanceVO.getBusinessId());
			taskVO.setDjType(instanceVO.getDjType());
			taskVO.setCompleteTime(resp.getEndTime());
			
			Date createTimeD = resp.getStartTime();
			taskVO.setCreateTime(createTimeD);
			String stayTimeLength = getDurationTime(createTimeD, resp.getEndTime());
			taskVO.setStayTimeLength(stayTimeLength);
			
			String processDefinitionId = resp.getProcessDefinitionId();
			String ysModelKey = processDefinitionId.split(":")[0];
			ProcessModelVO processModelVO = modelService.selectByYsModelKey(ysModelKey);
			if (processModelVO != null) {
//				UserVO startUserVO = userService.getDetail(instanceVO.getUserId());
//				taskVO.setName(startUserVO.getName() + "提交的" + processModelVO.getYsModelName());
				String name = resp.getHistoricProcessInstance().getName();
				taskVO.setName(name);
				taskVOs.add(taskVO);
				i++;
			}
		}
		rsPage.setTotal(total);
		rsPage.setData(taskVOs);
		return rsPage;
	}
	
	/*
	 * 判断流程实例是否已完成
	 */
	private boolean isFinishedOfProcessInstance(String ysUserId, String ysTenantId, String instanceId) {
		HistoricProcessInstanceResponse instance = null;
		try {
			instance = ysService.getProcessInstanceAllInfo(ysUserId, ysTenantId, instanceId);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "审批单据不存在");
		}
		if (instance == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "审批单据不存在");
		}
		Date endTime = instance.getEndTime();
	    if (endTime == null) {
	        return false;
	    }
	    return true;
	}
	
	/*
	 * 完成审批
	 * @param action(reject:驳回到上一步，rejectall:驳回到制单人，agree:同意,cancel:撤回)
	 */
	public boolean actionTask(Long businessId, int djType, String instanceId, String taskId, String comment, String action) {

		String ysUserId = getYsUserId(null);
		String ysTenantId = getYsTenantId(null);
		if (taskId == null) {
			if (action.equals(ActionEnum.CANCEL.getValue())) {
				// 撤销申请
				return cancelApproval(businessId, djType);
			}
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "任务不存在");
		}
		
		try {
			// 审批通过
			if (action.equals(ActionEnum.AGREE.getValue())) {
				if (comment == null || comment.trim().isEmpty()) {
					comment = ActionEnum.AGREE.getName();
				}
				boolean isSuccess = ysService.completeTask(ysUserId, ysTenantId, taskId, true, comment);
				
				Map<String, Object> paraMap = new HashMap<String, Object>();
				paraMap.put("comment", comment);
				paraMap.put("action", ActionEnum.AGREE.getName());
				int approvalState = ApprovalStatusEnum.APPROVAL.getValue();
				// 判断单据流程是否已经走完，如果已完成，更新单据的审批状态为已完成
				if (isFinishedOfProcessInstance(ysUserId, ysTenantId, instanceId)) {
					approvalState = ApprovalStatusEnum.FINISHED.getValue();
				}
				updateApprovalState(businessId, djType, approvalState, paraMap);
				
				return isSuccess;
			}
			if (action.equals(ActionEnum.REJECT.getValue())) {
				// 驳回到上一步,先判断任务是否能驳回
//				Boolean rejectAble = canTaskReject(ysUserId, ysTenantId, taskId);
//				if (!rejectAble) {
//					throw new CrmBusinessException(CrmCodeConstant.ServerError, "任务不能被驳回");
//				}
//				Map<String, Object> rsMap = ysService.rejectToPreviousActivity(ysUserId, ysTenantId, instanceId, taskId, comment);
				
				RejectInfoItemResponse[] rejectInfoItemResponses = getRejectInfoItems(ysUserId, ysTenantId, taskId);
				int arrLength = rejectInfoItemResponses.length;
				if (rejectInfoItemResponses == null || arrLength == 0) {
					throw new CrmBusinessException(CrmCodeConstant.ServerError, "任务不能被驳回");
				}
				String lastActivityId = rejectInfoItemResponses[arrLength - 1].getActivityId();
				Map<String, Object> rsMap = ysService.rejectToActivity(ysUserId, ysTenantId, instanceId, lastActivityId, comment);
				Map<String, Object> paraMap = new HashMap<String, Object>();
				paraMap.put("comment", comment);
				paraMap.put("action", ActionEnum.REJECT.getName());
				updateApprovalState(businessId, djType, ApprovalStatusEnum.APPROVAL.getValue(), paraMap);
				return true;
			}
			if (action.equals(ActionEnum.REJECTALL.getValue())) {
				// 驳回到制单人(不在流程设计器的控制中，任何时候都可驳回到制单人)
//				Map<String, Object> rsMap = ysService.rejectToInitialActivity(ysUserId, ysTenantId, instanceId, "", comment);
				deleteProcessInstance(businessId, djType);
				Map<String, Object> paraMap = new HashMap<String, Object>();
				paraMap.put("comment", comment);
				paraMap.put("action", ActionEnum.REJECTALL.getName());
				updateApprovalState(businessId, djType, 0, paraMap);
				return true;
			}
			

		} catch (RestException e) {
			e.printStackTrace();
		}
		throw new CrmBusinessException(CrmCodeConstant.ServerError, "操作失败");
		
	}
	
	/*
	 * 提醒审批
	 */
	public void remind(Long businessId, int djType, List<String> personlist) {
//		String startUserId = (String)instance.get("startUserId");
		// 获取发起人姓名
		Long userId = Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId));
		UserVO userVO = userService.getDetail(userId);
		String startUserName = userVO.getName();

		//获取流程名称
		Long bizTypeId = 0L;
		ProcessModelVO modelVO = modelService.selectByType(bizTypeId, djType);
		if (modelVO == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "审批流不存在");
		}
		String modelName = modelVO.getYsModelName();
		SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");
		String time = sdf.format(new Date());
		String[] userids = new String[personlist.size()];
		for(int i=0;i<personlist.size();i++){
			userids[i] = personlist.get(i);
		}
		ImParam param = new ImParam();
		String message = "审批通知: 新的待办 来自" + startUserName + 
				"于" + time + "提交的" + startUserName + modelName;
		param.setContent(message);
		param.setUsers(userids);
		param.setObjType(ProcessObjectInfoFactory.getInstance().getInfo(String.valueOf(djType)).getBeanName());
		param.setMessageType(IMType.APPROVALTYPE);
		param.setCreatUserId(userId);
		param.setObjId(businessId.toString());
		try {
			imBizService.SendImMessage(param);
		} catch (CrmMessageException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}
	
	/*
	 * 查询单个流程实例(详情)
	 */
	@SuppressWarnings("unchecked")
	public <T extends Serializable> T getDetail(Long businessId, int djType) {
		IProcessService service = new ProcessObtainUtil().getProcessService(djType,applicationContext);
		return (T)service.selectById(businessId);
	}
	
	/*
	 * 获取审批动作列表,如果流程已经结束，返回空列表；
	 * 如果流程未结束，操作人为发起人则返回元素为“撤回”，
	 * 操作人为审批人且不是待审人，返回空列表；
	 * 操作人为为审批人且是待审人，返回“同意”“驳回到上一步”“驳回到制单人”
	 */
	public List<ActionVO> getActions(String instanceId, String taskId) {
		List<ActionVO> actionVOs = new ArrayList<ActionVO>();
		
		ProcessInstanceVO instanceVO = instanceService.selectByInstanceId(instanceId);
		if (instanceVO == null) {
//			throw new CrmBusinessException(CrmCodeConstant.ServerError, "单据不存在");
			return actionVOs;
		}
		Long userId = Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId));
		String ysUserId = getYsUserId(userId);
		String ysTenantId = getYsTenantId(null);
		
		
		// taskId 为null时，请求来源于“我提交”列表的穿透
		if (taskId == null) {
			HistoricProcessInstanceResponse instanceMap = null;
			try {
				instanceMap = ysService.getProcessInstanceAllInfo(ysUserId, ysTenantId, instanceId);
			} catch (RestException e) {
				e.printStackTrace();
				throw new CrmBusinessException(CrmCodeConstant.ServerError, "单据不存在");
			}
			
			if (instanceMap == null) {
				return actionVOs;
			}
			
			Object endTime = instanceMap.getEndTime();
			if (endTime != null) {
				return actionVOs;
			}
		
			String startUserId = instanceMap.getStartUserId();
			boolean cancancel = canCancelInstance(instanceMap);
			// 制单人，判断是否可以撤回
			if (startUserId.equals(ysUserId) && cancancel) {
				ActionVO actionVO = new ActionVO();
				actionVO.setAction(ActionEnum.CANCEL.getValue());
				actionVO.setName(ActionEnum.CANCEL.getName());
				actionVOs.add(actionVO);
			}
			return actionVOs;
		}
		
		HistoricTaskInstanceResponse task = null;
		try {
			task = ysService.queryTask(ysUserId, ysTenantId, taskId);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "任务不存在");
		}
		if (task == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "任务不存在");
		}
		
		// 不是任务审批人，直接返回
		if (!task.getAssignee().equals(ysUserId)) {
			return actionVOs;
		}
		// 任务没有完成,返回动作包含同意，驳回到上一步，驳回到制单人
		if (!task.isFinished()) {
			ActionVO actionVO = new ActionVO();
			actionVO.setAction(ActionEnum.AGREE.getValue());
			actionVO.setName(ActionEnum.AGREE.getName());
			actionVOs.add(actionVO);
			
//			Boolean rejectAble = canTaskReject(ysUserId, ysTenantId, taskId);
			RejectInfoItemResponse[] rejectInfoItemResponse = getRejectInfoItems(ysUserId, ysTenantId, taskId);
			if (rejectInfoItemResponse != null && rejectInfoItemResponse.length > 0) {
				actionVO = new ActionVO();
				actionVO.setAction(ActionEnum.REJECT.getValue());
				actionVO.setName(ActionEnum.REJECT.getName());
				actionVOs.add(actionVO);
			}
			
			actionVO = new ActionVO();
			actionVO.setAction(ActionEnum.REJECTALL.getValue());
			actionVO.setName(ActionEnum.REJECTALL.getName());
			actionVOs.add(actionVO);
			
			return actionVOs;
		}
		return actionVOs;
	}
	
	/*
	 * 创建子租户
	 */
	public void saveTenant(Long tenantId) {
		if (tenantId == null) {
			tenantId = Long.parseLong(InvocationInfoProxy.getTenantid());
		}
		try {
			getYsTenantId(null);
			return;
		} catch (CrmBusinessException e) {
			
		}
		
		SysTenantVO tenantVO = tenantService.getVOById(SysTenantVO.class, tenantId);
		
		String name = tenantVO.getCompanyName();
		String address = tenantVO.getCompanyAddress();
		String code = tenantId.toString();
		
		String ysTenantId = "";
		try {
			TenantResponse resp = ysService.saveTenant(name, code, address);
			ysTenantId = resp.getId();
		} catch (RestException e) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "创建子租户失败");
		} catch (CrmBusinessException e) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, e.getMessage());
		}
		
		if (ysTenantId.isEmpty()) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "创建子租户失败");
		}
		// 保存ysTenantId
		BpubTenantDO bpubTenantDo = new BpubTenantDO();
		bpubTenantDo.setTenantId(tenantId);
		bpubTenantDo.setYsTenantId(ysTenantId);
		bpubTenantService.saveVO(bpubTenantDo);
	}
	
	/*
	 * 同步部门,人员,角色(不能实时同步，可以设定时任务，或者触发入口)
	 */
	public void synDeptsAndUsers() {
		log.debug("进入云审批同步方法");
		// 临时调用saveTenant，正式部署应该删去 BEGIN(shenhui)
		saveTenant(null);
		// END
		
		Long tenantId = Long.parseLong(InvocationInfoProxy.getTenantid());
		String ysTenantId = getYsTenantId(tenantId);
		
		// 同步部门
		// 获取部门列表
		List<Map<String, Object>> deptList = sysOrgService.getAllDepts();
		if (deptList == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "未获取到部门信息");
		}
		try {
			ysService.synDepts(ysTenantId, deptList);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "同步部门失败");
		}

		// 同步用户组(角色)
		// 获取角色列表(同步用户组)
//		Map<String, Object> param = new HashMap<String, Object>();
//		param.put("tenantId", Long.parseLong(InvocationInfoProxy.getTenantid()));
		List<RoleVO> roleVos = roleService.tenantRoles(InvocationInfoProxy.getTenantid());
		if (roleVos == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "未获取到角色信息");
		}
		try {
			ysService.synUserGroups(ysTenantId, roleVos);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "同步角色失败");
		}
		
		// 同步用户
		// 获取用户列表
		List<Map<String, Object>> userList = userService.getAllUsers();
		if (userList == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "未获取到用户信息");
		}
		List<UserResponse> responseSaveUsers = null;
		try {
			responseSaveUsers = ysService.synUsers(ysTenantId, userList);
		} catch (RestException e) {
			e.printStackTrace();
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "同步用户失败");
		}
		
		if (responseSaveUsers == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "同步用户失败");
		}
		// 保存ysUserId到crm中，方便以后查询使用
		List<Map<String, Object>> ysUserList = new ArrayList<Map<String,Object>>();
		for (UserResponse m : responseSaveUsers) {
			Map<String, Object> ysUser = new HashMap<String, Object>();
			String[] userCodeArr = m.getCode().split("_");
			if (userCodeArr.length <= 1) continue;
			ysUser.put("userId", Long.parseLong(userCodeArr[1]));
			ysUser.put("ysUserId", m.getId());
			ysUserList.add(ysUser);
		}
		approvalUserService.synYsUserIds(ysUserList);
	}
	
	/*
	 * 判断任务是否能驳回(作为判断“驳回到上一步”按钮是否显示的判断依据)
	 */
//	private boolean canTaskReject(String ysUserId, String ysTenantId, String taskId) {
//		try {
//			Map<String, Object> rs = ysService.rejectCheck(ysUserId, ysTenantId, taskId);
//			Boolean rejectAble = (Boolean)rs.get("rejectAble");
//			return rejectAble;
//		} catch (RestException e) {
//			e.printStackTrace();
//			return false;
//		}
//	}
	
	/*
	 * 任务驳回状态检查
	 */
	private RejectInfoItemResponse[] getRejectInfoItems(String ysUserId, String ysTenantId, String taskId) {
		try {
			RejectInfoItemResponse[] rs = ysService.getRejectInfoItems(ysUserId, ysTenantId, taskId);
			return rs;
		} catch (RestException e) {
			e.printStackTrace();
			return null;
		}
	}

}
